package com.har01d.lang.compiler.visitor;

import com.har01d.lang.antlr.Har01dBaseVisitor;
import com.har01d.lang.antlr.Har01dParser;
import com.har01d.lang.compiler.domain.Scope;
import com.har01d.lang.compiler.domain.statement.FieldDeclaration;
import com.har01d.lang.compiler.domain.statement.expression.Expression;
import com.har01d.lang.compiler.domain.type.Type;
import com.har01d.lang.compiler.domain.variable.Field;
import com.har01d.lang.compiler.exception.InvalidSyntaxException;
import com.har01d.lang.compiler.util.TypeResolver;
import com.har01d.lang.compiler.visitor.statement.expression.ExpressionVisitor;

public class FieldVisitor extends Har01dBaseVisitor<FieldDeclaration> {

    private final ExpressionVisitor expressionVisitor;
    private final Scope scope;

    public FieldVisitor(ExpressionVisitor expressionVisitor, Scope scope) {
        this.expressionVisitor = expressionVisitor;
        this.scope = scope;
    }

    @Override
    public FieldDeclaration visitField(Har01dParser.FieldContext ctx) {
        String category = ctx.c.getText();
        String name = ctx.name().getText();

        if (scope.isFieldExist(name)) {
            throw new InvalidSyntaxException("Field '" + name + "' already declared!", ctx.name());
        }

        Type type = null;
        Expression expression = null;
        if (ctx.type() != null) {
            type = TypeResolver.resolve(ctx.type());
        }

        if (ctx.expression() != null) {
            expression = ctx.expression().accept(expressionVisitor);
            if (type == null) {
                type = expression.getType();
            }
        }

        Field field = scope.addField(name, type, expression != null, "val".equals(category));
        return new FieldDeclaration(field, expression);
    }

}
